import pandas as pd

def get_feature_importance(model_path, feature_names=None, importance_type='split'):
    """
    获取LightGBM特征重要性排名
    
    参数：
    model -- 训练好的LightGBM模型（Booster或sklearn接口）
    feature_names -- 特征名称列表，默认从模型获取
    importance_type -- 重要性类型：'split'或'gain'，默认split
    
    返回：
    排序后的DataFrame（特征名，重要性值）
    """

     # 加载模型
    model = lgb.Booster(model_file=model_path)
    
    # 处理不同模型接口
    if isinstance(model, lgb.Booster):
        importance = model.feature_importance(importance_type=importance_type)
        features = model.feature_name() if feature_names is None else feature_names
    else:  # sklearn接口
        importance = model.booster_.feature_importance(importance_type=importance_type)
        features = feature_names if feature_names else model.booster_.feature_name()
    
    # 异常处理
    if len(features) != len(importance):
        raise ValueError("特征名称数量与重要性值不匹配")
    
    # 构建排序表格
    df = pd.DataFrame({
        'Feature': features,
        'Importance': importance
    }).sort_values('Importance', ascending=False)
    
    return df.reset_index(drop=True)



"""
    分析指定分类列的分布情况
    
    参数：
    df: pd.DataFrame - 待分析的数据框
    label_col: str - 目标列名（默认'label'）
    
    返回：
    pd.DataFrame - 包含数量统计和比例分布的结果表
"""
import pandas as pd

def analyze_label_distribution(df, label_col='label'):
   
    # 统计各标签数量
    count_series = df[label_col].value_counts(dropna=False)
    
    # 计算比例（带格式化）
    dist_df = (
        count_series.rename('数量')
        .to_frame()
        .assign(比例=lambda x: (x['数量'] / x['数量'].sum()).map("{:.2%}".format))
        .rename_axis('类别')
        .reset_index()
    )
    
    # 添加总数行
    total_row = pd.DataFrame({
        '类别': ['总计'],
        '数量': [dist_df['数量'].sum()],
        '比例': ["{:.2%}".format(1.0)]
    })
    
    return pd.concat([dist_df, total_row], ignore_index=True)



"""
    寻找能显著提升类别3占比的特征和临界值
    :param df: 包含特征和目标列的数据框
    :param target_col: 目标列名称
    :param class3_value: 类别3的值
    :param min_ratio: 需要达到的最小类别3占比
    :return: 提升效果最好的特征及其临界值
"""
import pandas as pd
import numpy as np
from tqdm import tqdm

def find_features_boosting_class3(df, target_col='label', class3_value=3, min_ratio=0.05):
    
    # 1. 基础统计
    total_count = len(df)
    class3_count = len(df[df[target_col] == class3_value])
    base_ratio = class3_count / total_count
    print(f"基础统计: 总样本数={total_count}, 类别3数量={class3_count}, 占比={base_ratio:.2%}")
    
    # 2. 预处理：仅保留数值型特征
    numeric_features = df.select_dtypes(include=['float64', 'int64']).columns.tolist()
    numeric_features = [f for f in numeric_features if f != target_col]
    print(f"分析特征数量: {len(numeric_features)}个")
    
    # 3. 结果存储
    results = []
    
    # 4. 遍历每个特征
    for feature in tqdm(numeric_features, desc="分析特征"):
        # 跳过缺失值过多的特征
        if df[feature].isnull().mean() > 0.3:
            continue
            
        # 尝试多个分位数作为临界值
        for q in np.arange(0.05, 0.95, 0.05):
            # 尝试上分位数筛选 (特征 > 分位值)
            threshold = df[feature].quantile(q)
            mask = df[feature] > threshold
            subset = df[mask]
            
            if len(subset) == 0:
                continue
                
            # 计算类别3占比
            subset_class3 = subset[subset[target_col] == class3_value]
            ratio = len(subset_class3) / len(subset)
            
            # 计算提升效果指标
            lift = ratio / base_ratio  # 提升倍数
            coverage = len(subset) / total_count  # 覆盖率
            
            # 存储结果
            results.append({
                'feature': feature,
                'direction': '>',
                'quantile': q,
                'threshold': threshold,
                'ratio': ratio,
                'lift': lift,
                'coverage': coverage,
                'sample_count': len(subset),
                'class3_count': len(subset_class3)
            })
            
            # 尝试下分位数筛选 (特征 < 分位值)
            mask = df[feature] < threshold
            subset = df[mask]
            
            if len(subset) == 0:
                continue
                
            # 计算类别3占比
            subset_class3 = subset[subset[target_col] == class3_value]
            ratio = len(subset_class3) / len(subset)
            
            # 计算提升效果指标
            lift = ratio / base_ratio
            coverage = len(subset) / total_count
            
            # 存储结果
            results.append({
                'feature': feature,
                'direction': '<',
                'quantile': q,
                'threshold': threshold,
                'ratio': ratio,
                'lift': lift,
                'coverage': coverage,
                'sample_count': len(subset),
                'class3_count': len(subset_class3)
            })
    
    # 5. 转换为DataFrame并分析结果
    results_df = pd.DataFrame(results)
    
    # 筛选达到目标占比的结果
    qualified = results_df[results_df['ratio'] >= min_ratio]
    
    if len(qualified) == 0:
        print("未找到能提升类别3占比至5%以上的特征")
        return None
    
    # 按提升倍数排序
    best_lift = qualified.sort_values('lift', ascending=False).iloc[0]
    
    # 按覆盖率排序（考虑实用性的最佳选择）
    best_coverage = qualified.sort_values('coverage', ascending=False).iloc[0]
    
    # 按平衡指标排序（提升倍数*覆盖率）
    qualified['balanced_score'] = qualified['lift'] * qualified['coverage']
    best_balanced = qualified.sort_values('balanced_score', ascending=False).iloc[0]
    
    return {
        'all_results': results_df,
        'qualified': qualified,
        'best_lift': best_lift,
        'best_coverage': best_coverage,
        'best_balanced': best_balanced
    }
